/*
    nspire-gamekit - a simple homebrew game framework
    Copyright (C) 2011  Daniel Tang

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <os.h>
#include "autorelease.h"
#include "objects.h"
#include "types/ngk.h"

/* I'm starting to hate doubley linked lists */

struct NGKObjnodePriv {
    NGKObjnodePriv *next;
    NGKObjnodePriv *prev;
    NGKGameObject* ptr;
};

static NGKObjnodePriv* firstElement = NULL;
static NGKObjnodePriv* lastElement = NULL;

NGKGameObject* gameObjectMake() {
    NGKGameObject *ptr = gameAutoMalloc(sizeof(NGKGameObject));
    if (!ptr) return NULL;
    memset(ptr, 0, sizeof(NGKGameObject));
    return ptr;
}

void gameObjectAdd(NGKGameObject* obj) {
    NGKObjnodePriv *node = gameAutoMalloc(sizeof(NGKObjnodePriv));
    if (!node) return;
    if (!obj) return;
    if (obj->node) return; //Already attached to a node
    
    node->next = NULL;
    node->prev = NULL;
    node->ptr = obj;

    obj->node = node;
    
    if (firstElement == NULL) {
        firstElement = node;
    }
    if (lastElement) {
        lastElement->next = node;
        node->prev = lastElement;
    }
    lastElement = node;
    
    if (obj->events.init) obj->events.init(obj);
    gameAutoRetain(obj);
}



void gameObjectRemove(NGKGameObject *ptr) {
    /* Unlink from the double linked list */
    //Oh god, this code is horrible
    if (!ptr->node) return;
    if (ptr->node->prev) ptr->node->prev->next = ptr->node->next;
    if (ptr->node->next) ptr->node->next->prev = ptr->node->prev;
    
    if (firstElement == ptr->node) firstElement = ptr->node->next;
    if (lastElement == ptr->node) lastElement = ptr->node->prev;
    
    ptr->node = NULL;
    gameAutoFree(ptr->node);
    gameAutoRelease(ptr);
}

void gameObjectRemoveAll() {
    NGKObjnodePriv *node = firstElement;
    NGKObjnodePriv *next = node;
    while (node) { 
        next = node->next;
        gameObjectRemove(node->ptr);
        node = next;
    }
    firstElement = NULL;
    lastElement = NULL;
}